import {DataRouter} from "../frame/dataSource/DataRouter";
import {GlobalEnv} from "../utils/GlobalEnv";
import {TimeControllerOpt} from "../controller/model/ControllerOpt";
import {TimeController} from "../controller/TimeController";
import {DataRouterUtil} from "../utils/router/DataRouterUtil";
import {UnitController} from "../controller/UnitController";
import {ConfigKey} from "../constant/ConfigConstant";
import Configer from "../frame/apiModel/config/Configer";
import {Logger} from "../frame/apiModel/config/Logger";
import {CodeUtil} from "../frame/codeAdapter/CodeUtil";
import {PlayerFactory} from "../frame/PlayerFactory";
import {ModelFactory} from "../frame/apiModel/adapterModel/model5/ModelFactory";
import {UnitJson} from "../frame/apiModel/model/StoreJson";
import {RewardType} from "../type/Type";
import {AttackMonsterData, LocType, PathData, UnitType} from "../frame/dataSource/DataModel";
import {UnitModel} from "../frame/apiModel/adapterModel/model3/UnitModel";
import {PlayerModel} from "../frame/apiModel/adapterModel/model4/PlayerModel";
import {TaskController} from "../controller/TaskController";
import {PlayerDataKey, UnitDataKey} from "../frame/dataSource/DataSource";
import {LocalSaveModel} from "../frame/apiModel/adapterModel/model1/LocalSaveModel";

export function attackMonsterTrigger() {
    const difficult = GlobalEnv.difficult;
    const difficultData = DataRouterUtil.getDifficultData(difficult);
    const attackMonsterDatas = DataRouterUtil.getAttackMonsterDatasByMode(difficultData.mode);

    const len = attackMonsterDatas.length;

    if (len === 0) {
        Logger.toastSys(`出兵系统已关闭`);
        return;
    }
    // initPathTrigger();

    const wave = GlobalEnv.wave;
    const monsterData = attackMonsterDatas[wave - 1];
    let interval = Configer.getConfig(ConfigKey.attackMonsterNullTurnTime);
    if (monsterData) {
        interval = monsterData.interval;
    } else {
        return;
    }
    // const opt = new TimeControllerOpt(`第${wave}波`, nextWave, 1);
    let opt;
    if (!CodeUtil.isNullOrZero(Configer.getConfig(ConfigKey.attackMonsterTimerText))) {
        opt = new TimeControllerOpt(`第${wave}波`, nextWave, 1);
    } else {
        opt = new TimeControllerOpt(undefined, nextWave, 1);
    }
    GlobalEnv.waveTimer = TimeController.getInstance().startTimer({opt, time: interval})
}

function nextWave() {
    // 当前波数出怪
    const difficult = GlobalEnv.difficult;
    const difficultData = DataRouterUtil.getDifficultData(difficult);
    const attackMonsterDatas = DataRouterUtil.getAttackMonsterDatasByMode(difficultData.mode);

    const wave = GlobalEnv.wave;

    const tempWave = wave;

    const maxWave = difficultData?.wave;
    if (maxWave && wave > maxWave) {
        Logger.toastProduct('到达当前难度最大波数, 停止出兵!');
        return;
    }
    const monsterData: AttackMonsterData = attackMonsterDatas[wave - 1];
    let time = Configer.getConfig(ConfigKey.attackMonsterNullTurnTime);
    if (monsterData) {
        const reward = monsterData.beforeReward;
        if (reward) {
            PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                (tempPlayer) => {
                    const hero = GlobalEnv.getHero(tempPlayer);
                    TaskController.getInstance().reward(hero, hero, RewardType.bag, reward);
                }
            )
        }

        if (!CodeUtil.isNullOrZero(monsterData.mode)) {
            if (monsterData.mode === difficultData.mode) {
            } else {
                return;
            }
        }

        time = monsterData.time;
        const des = monsterData.des;
        if (des) {
            Logger.toastProduct(des)
        }
    }

    let autoClearHurtNum = Configer.getConfig(ConfigKey.autoClearHurtNum);
    if (!CodeUtil.isNullOrZero(autoClearHurtNum)) {
        UnitController.getInstance().clearHurtNum();
    }


    let times = 0;
    const maxTimes = time;
    const createAttackMonsterFun = function () {
        createAttackMonster(wave, times, maxTimes);
        times = times + 1;
    }
    const createAttackMonsterOpt = new TimeControllerOpt(undefined, createAttackMonsterFun, time);
    GlobalEnv.waveTimer = TimeController.getInstance().startTimer({opt: createAttackMonsterOpt, time: 1});

    if (GlobalEnv.getAllBeEnd()) {
        Logger.toastProduct('游戏结束, 停止出兵!');
        return;
    }

    const waveAuto = Configer.getConfig(ConfigKey.waveAuto);
    // 是否切换到下一波
    if (!CodeUtil.isNullOrZero(waveAuto)) {
        GlobalEnv.addWave(1);
    }
}

function createAttackMonster(wave: number, times: number, maxTimes: number) {
    const difficult = GlobalEnv.difficult;
    const difficultData = DataRouterUtil.getDifficultData(difficult);
    const attackMonsterDatas = DataRouterUtil.getAttackMonsterDatasByMode(difficultData.mode);
    const monsterData = attackMonsterDatas[wave - 1];
    const nextMonsterData = attackMonsterDatas[wave];

    if (times === (maxTimes - 1)) {
        rewardNextWave(monsterData, nextMonsterData)
    }

    const enemyTeam = Configer.getConfig(ConfigKey.enemyTeam) as number;
    const enemyPlayer = GlobalEnv.getTeamFreePlayer(enemyTeam);
    if (enemyPlayer?.isValid()) {
    } else {
        return;
    }

    if (monsterData) {
        const area = monsterData.birth_point;
        const areaArr = CodeUtil.getArrBySplit(area);
        const path = monsterData.path;
        const pathArr = CodeUtil.getArrBySplit(path);
        const checkPlayer = monsterData.checkPlayer;

        const monsterIds = monsterData.monsterId;
        const monsterIdArr = CodeUtil.getArrBySplit(monsterIds);

        const creamIds = monsterData.creamId;
        const creamIdArr = CodeUtil.getArrBySplit(creamIds);

        const initFun = (unit: UnitModel, rectName: string, pathData: PathData, player?: PlayerModel) => {
            if (player) {
                player?.addAttackMonster(unit);
            } else {
                GlobalEnv.addAllAttackMonster(unit);
            }
            const unitData = unit.template;

            unit.removeGuardPosition();
            UnitController.getInstance().addEnemyUnit(unit);
            UnitController.getInstance().unitUsePath(rectName, pathData, unit);

            if (unitData.unit_type === UnitType.shareBoss) {
                UnitController.getInstance().addShareBoss(unit);
            }
        }
        // checkPlayer情况下 出生地的每个地点按玩家是否在线来出怪
        for (let areaIndex = 0; areaIndex < areaArr.length; areaIndex++) {
            let tempPlayer: PlayerModel;
            if (!CodeUtil.isNullOrZero(checkPlayer)) {
                tempPlayer = PlayerFactory.getInstance().getPlayer(areaIndex);
                const isPlaying = tempPlayer?.isNotEndPlaying();
                if (isPlaying) {
                } else {
                    continue;
                }
            }
            const rectName = areaArr[areaIndex];
            const pathId = pathArr[areaIndex];
            const monsterId = monsterIdArr[areaIndex];
            const creamId = creamIdArr[areaIndex];
            // const monsterNum = GlobalEnv.getAttackMonsterNum();
            // const maxNum = ConstantUtil.getConfig(ConfigKey.attackMonsterMaxNum);
            // if (monsterNum >= maxNum) {
            //     return;
            // }
            const rect = ModelFactory.getInstance().getRectModel(rectName);

            const frequency = monsterData.frequency;

            let locType = monsterData.locType;
            let loc = rect.getRandomLocModel();

            if (locType === LocType.center) {
                loc = rect.getCenterLocModel();
            }
            let arr: UnitModel[] = [];

            if (monsterId) {
                const unitJson: UnitJson = { id: monsterId, e: 0 };
                const monsters = UnitController.getInstance().createUnit(frequency, unitJson, enemyPlayer, loc, 0, false, tempPlayer);
                arr.push(...monsters);
            }

            if (times === 0) {
                if (creamId) {
                    const unitJson: UnitJson = { id: creamId, e: 0 };
                    const bossArr = UnitController.getInstance().createUnit(1, unitJson, enemyPlayer, loc, 0, false, tempPlayer);
                    arr.push(...bossArr);
                }
            }
            const pathData = DataRouter.getPathDataByPathId(pathId);
            for (let i = 0; i < arr.length; i++) {
                const unit = arr[i];
                initFun(unit, rectName, pathData, tempPlayer);
            }
        }

        if (times === 0) {
            const bossId = monsterData.bossId;
            if (bossId) {
                const rectName = monsterData.boss_birth_point;
                const pathId = monsterData.boss_path;
                const rect = ModelFactory.getInstance().getRectModel(rectName);

                let locType = monsterData.locType;
                let loc = rect.getRandomLocModel();

                if (locType === LocType.center) {
                    loc = rect.getCenterLocModel();
                }

                const unitJson: UnitJson = { id: bossId, e: 0 };
                const monsters = UnitController.getInstance().createUnit(1, unitJson, enemyPlayer, loc, 0, false);
                const pathData = DataRouter.getPathDataByPathId(pathId);

                for (let i = 0; i < monsters.length; i++) {
                    const unit = monsters[i];
                    initFun(unit, rectName, pathData);
                }
            }
        }

    }
}

function rewardNextWave(currentMonsterData: AttackMonsterData, nextMonsterData: AttackMonsterData) {
    const fun = () => {

        const newWave = GlobalEnv.wave;

        let newInterval = Configer.getConfig(ConfigKey.attackMonsterNullTurnTime)
        if (nextMonsterData) {
            newInterval = nextMonsterData.interval;
        }
        let nextWaveOpt;
        if (!CodeUtil.isNullOrZero(Configer.getConfig(ConfigKey.attackMonsterTimerText))) {
            nextWaveOpt = new TimeControllerOpt(`第${newWave}波`, nextWave, 1);
        } else {
            nextWaveOpt = new TimeControllerOpt(undefined, nextWave, 1);
        }
        GlobalEnv.waveTimer = TimeController.getInstance().startTimer({opt: nextWaveOpt, time: newInterval})
    }
    const afterRewardFun = () => {
        // Logger.toastProduct(`清空${tempWave}波进攻怪，获得波次奖励`);
        const reward = currentMonsterData?.afterReward;
        if (reward) {
            PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                (tempPlayer) => {
                    const hero = GlobalEnv.getHero(tempPlayer);
                    TaskController.getInstance().reward(hero, hero, RewardType.bag, reward);
                }
            )
        }
    }

    GlobalEnv.nextWaveCallBack.push(afterRewardFun);

    const awaitWave = Configer.getConfig(ConfigKey.awaitWave);
    if (!CodeUtil.isNullOrZero(awaitWave)) {
        GlobalEnv.nextWaveCallBack.push(fun);
    } else {
        fun();
    }
}


